import logging

from aiogram import Bot
from fluentogram import TranslatorRunner

from src.application.order.enums import ProxyStatus
from src.application.order.service import OrderService
from src.application.proxy.service import ProxyService
from src.infrastructure.db.services.allowed_ips import get_allowed_ip_by_order
from src.infrastructure.db.services.orders.common import get_order
from src.infrastructure.db.services.proxy import change_expired_proxy, get_proxy
from src.infrastructure.db.services.users import get_user
from src.infrastructure.ssh.async_ssh_connector import change_expired_proxies
from src.infrastructure.utils.helpers import get_server_proxies
from src.presentation.tg_bot.services.tg_helpers import broadcast
from src.presentation.tg_bot.worker.exception_handler import exception_handler

logger = logging.getLogger(__name__)


@exception_handler
async def change_proxy(
    ctx,
    locale: TranslatorRunner,
    user_id: int,
    order_id: int,
    proxy_id: int,
    new_proxy_id: int,
    country_id: int = None,
    provider_id: int = None,
):
    bot: Bot = ctx["bot"]
    proxy_service: ProxyService = ctx["proxy_service"]
    order_service: OrderService = ctx["order_service"]

    try:
        order = await order_service.get_order_by_id(order_id, joined=True)
        user = await get_user(session, order.user.tg_id, joined=True)
        old_proxy = await get_proxy(session, proxy_id)
        new_proxy = await get_proxy(session, new_proxy_id)

        try:
            order.proxies.remove(old_proxy)
            user.proxies.remove(old_proxy)
        except ValueError:
            pass

        allowed_ip = await get_allowed_ip_by_order(session, user.telegram_id, order.id)

        logger.info(f"Меняю прокси в заказе №{order_id} c {old_proxy} на {new_proxy}")

        if old_proxy:
            old_proxies_creds = [
                {
                    "server_id": old_proxy.server_id,
                    "login": old_proxy.login,
                    "password": old_proxy.password,
                    "reload_link": old_proxy.reload_link,
                    "port_https": old_proxy.port_https,
                }
            ]

            await change_expired_proxy(session, [old_proxy])

            server_proxies = await get_server_proxies(session, old_proxies_creds, [old_proxy])

            for server, proxies in server_proxies.items():
                await change_expired_proxies(server, proxies, allowed_ip)

        order.proxies.append(new_proxy)
        user.proxies.append(new_proxy)
        new_proxy.status = ProxyStatus.sold

        if country_id:
            order.country_id = country_id
        if provider_id:
            order.provider_id = provider_id

        await session.commit()

        await broadcast(
            bot,
            [user_id],
            locale.get(
                "new-proxy-msg",
                login=new_proxy.login,
                password=new_proxy.password,
                ip_address=new_proxy.server.ip_address,
                port=new_proxy.port_https,
            ).replace("\xa0", ""),
        )
    except Exception:
        await broadcast(bot, [user_id], locale.get("change-proxy-error"))
